package se.rkrantz.simpleraid.web.controller.profile;

import java.io.IOException;
import java.security.Principal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.joda.time.DateTime;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import se.rkrantz.simpleraid.hibernate.dao.WowCharacterDao;
import se.rkrantz.simpleraid.hibernate.domain.User;
import se.rkrantz.simpleraid.hibernate.domain.WowCharacter;
import se.rkrantz.simpleraid.service.user.UserService;

@Controller
public class ProfileController {
	
	private final Logger logger = LoggerFactory.getLogger(ProfileController.class);
	//private static final Log logger = LogFactory.getLog(ProfileController.class);
	@Autowired private UserService userService;
	@Autowired private WowCharacterDao wowCharacterDao;
	
	private Map<String, ProfileController.AvatarCacheObject> avatarCache = null;
	
	@RequestMapping("/profile.html")
	public String showProfile(Model model, Principal principal) {
		
		//Set<WowCharacter> characters = userService.getWowCharacters(principal);
		
		//model.addAttribute("characters", characters);
		
		return "profile";
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/listCharacters.html")
	@ResponseBody
	public String listCharacters(Principal principal) {
		JSONArray list = new JSONArray();
		
		Set<WowCharacter> characters = userService.getWowCharacters(principal);
		User user = null;
		for (WowCharacter wc : characters) {
			if (user == null) {
				user = wc.getUser();
			}
			JSONObject character = new JSONObject();
			character.put("characterId", wc.getCharacterId());
			character.put("characterName", wc.getCharacterName());
			character.put("characterClass", wc.getCharacterClass().toString());
			character.put("countRaids", wc.getSignups().size());
			character.put("countPasses", wowCharacterDao.numberOfPasses(wc.getCharacterId() + ""));
			character.put("isPrimary", user.getPrimaryCharacter().getCharacterId() == wc.getCharacterId());
			list.add(character);
		}
		logger.debug("Listed {} character for user {}", list.size(), principal.getName());
		return list.toJSONString();
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping("/userInfo.html")
	@ResponseBody
	public String userInfo(Principal principal) {
		JSONObject userJSON = new JSONObject();
		
		userJSON.put("userName", principal.getName());
		userJSON.put("userEmail", "abc@gah.com");
		
		return userJSON.toJSONString();
	}
	
	@RequestMapping("/addProfile.html")
	public String addProfile(@RequestParam String characterName, @RequestParam String characterClass, @RequestParam(defaultValue="false") String primaryCharacter, Model model, Principal principal) {
		boolean isPrimary = false;
		if ("true".equalsIgnoreCase(primaryCharacter)) {
			isPrimary = true;
		}
		userService.addWowCharacter(principal, characterName, characterClass, isPrimary);
		
		return "redirect:profile.html";
	}
	
	@RequestMapping("/changePrimary.html")
	@ResponseBody
	public String changePrimary(@RequestParam String characterId, Model model, Principal principal) {
		logger.info("Changing primary characters for '{}' to character with Id: {}", principal.getName(), characterId);
		return userService.setPrimaryCharacter(principal, characterId);
	}
	
	@RequestMapping("/numberPasses.html")
	@ResponseBody
	public String numberPasses(@RequestParam String characterId, Model model, Principal principal) {
		return wowCharacterDao.numberOfPasses(characterId) + "";
	}
	
	
	
	@RequestMapping("/getAvatar.html")
	@ResponseBody
	public String getAvatar(@RequestParam String characterName, Model model) {
		/*
		 * This is handled server-side due to cross-domain request limitations.
		 */
		try {
			if (avatarCache == null) {
				avatarCache = new HashMap<String, ProfileController.AvatarCacheObject>();
			}
			if (avatarCache.containsKey(characterName) && new Date().before(((AvatarCacheObject)avatarCache.get(characterName)).expires)) {
				logger.debug("Returning cached avater for character {}", characterName);
				return ((AvatarCacheObject)avatarCache.get(characterName)).url;
			}
			
			HttpClient client = new HttpClient();
			GetMethod method = new GetMethod("http://eu.battle.net/api/wow/character/Alonsus/"+characterName);
			client.executeMethod(method);
			JSONObject characterData = (JSONObject)JSONValue.parse(method.getResponseBodyAsString());
			
			if (characterData.containsKey("thumbnail")) {
				String url = "http://eu.battle.net/static-render/eu/" + characterData.get("thumbnail");
				avatarCache.put(characterName, new AvatarCacheObject(url, new DateTime().plusHours(1).toDate())); // 1 hour cache
				logger.debug("Cached avater for character {}", characterName);
				return url;
			}
		} catch (HttpException e) {
			logger.warn("Failed to retrieve character avatar from Blizzard", e);
		} catch (IOException e) {
			logger.warn("Failed to retrieve character avatar from Blizzard", e);
		}
		return "";
	}
	
	private class AvatarCacheObject {
		public final String url;
		public final Date expires;
		
		public AvatarCacheObject(String url, Date expires) {
			this.url = url;
			this.expires = expires;
		}
	}
}
